package ru.agiledev.akb.client.window;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import ru.agiledev.akb.client.*;
import ru.agiledev.akb.shared.User;


/**
 * Created by a.kirillov
 * Date: 3/31/11 Time: 11:08 PM
 */
public class RegistrationWindow extends DialogBox {

    private TextBox loginField;
    private TextBox firstNameField;
    private TextBox lastNameField;
    private TextBox affilationField;
    private TextBox emailField;
    private PasswordTextBox passwordField;
    private PasswordTextBox passwordConfirmField;
    private HorizontalPanel loginError;
    private HorizontalPanel firstNameError;
    private HorizontalPanel lastNameError;
    private HorizontalPanel emailError;
    private HorizontalPanel passwordError;
    private HorizontalPanel passwordConfirmError;


    private final ValidationServiceAsync validationService = GWT.create(ValidationService.class);
    private final RegistrationServiceAsync registrationService = GWT.create(RegistrationService.class);

    public RegistrationWindow(int x, int y) {
        setModal(true);
        setAnimationEnabled(true);
        setText("Регистрация");
        addStyleName("registrationDialogBox");
        setPopupPosition(x, y);

        VerticalPanel registrationPanel = new VerticalPanel();
        registrationPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);


        HorizontalPanel words = new HorizontalPanel();
        HTML hello = new HTML("<center>Регистрация необходима для того, чтобы Вы могли создавать, просматривать и редактировать данные, " +
                "формирующие базу знаний. К Вашему имени пользователя будет привязана вся информация, с которой Вы работали в " +
                "данном Интернет-сервисе. Ваши пользовательские данные являются конфиденциальными и не будут использоваться где-либо, кроме " +
                "данного Интернет-сервиса<center>");
        words.add(hello);

        HorizontalPanel enterYourData = new HorizontalPanel();
        enterYourData.setSpacing(4);
        enterYourData.setHorizontalAlignment(HorizontalPanel.ALIGN_RIGHT);
        HTML inputPrompt = new HTML("<b>Заполните форму</b>");
        enterYourData.add(inputPrompt);

        HorizontalPanel loginPanel = new HorizontalPanel();
        loginPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        loginPanel.setSpacing(4);

        Label login = new Label("Логин");
        loginField = new TextBox();
        loginField.getElement().setId("login");

        loginPanel.add(login);
        loginPanel.add(loginField);

        loginError = new HorizontalPanel();
        loginError.setSpacing(2);

        HorizontalPanel firstNamePanel = new HorizontalPanel();
        firstNamePanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        firstNamePanel.setSpacing(4);
        Label firstName = new Label("Имя");
        firstNameField = new TextBox();
        firstNameField.getElement().setId("firstName");

        firstNamePanel.add(firstName);
        firstNamePanel.add(firstNameField);

        firstNameError = new HorizontalPanel();
        firstNameError.setSpacing(2);

        HorizontalPanel lastNamePanel = new HorizontalPanel();
        lastNamePanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        lastNamePanel.setSpacing(4);
        Label lastName = new Label("Фамилия");
        lastNameField = new TextBox();
        lastNameField.getElement().setId("lastName");

        lastNamePanel.add(lastName);
        lastNamePanel.add(lastNameField);

        lastNameError = new HorizontalPanel();
        lastNameError.setSpacing(2);

        HorizontalPanel affilationPanel = new HorizontalPanel();
        affilationPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        affilationPanel.setSpacing(4);
        Label affilation = new Label("Организация");
        affilationField = new TextBox();

        affilationPanel.add(affilation);
        affilationPanel.add(affilationField);

        HorizontalPanel emailPanel = new HorizontalPanel();
        emailPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        emailPanel.setSpacing(4);
        Label email = new Label("E-mail");
        emailField = new TextBox();
        emailField.getElement().setId("email");

        emailPanel.add(email);
        emailPanel.add(emailField);

        emailError = new HorizontalPanel();
        emailError.setSpacing(2);

        HorizontalPanel passwordPanel = new HorizontalPanel();
        passwordPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        passwordPanel.setSpacing(4);
        passwordField = new PasswordTextBox();
        passwordField.getElement().setId("pwd");
        Label password = new Label("Пароль");

        passwordPanel.add(password);
        passwordPanel.add(passwordField);

        passwordError = new HorizontalPanel();
        passwordError.setSpacing(2);

        HorizontalPanel passwordConfirmPanel = new HorizontalPanel();
        passwordConfirmPanel.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        passwordConfirmPanel.setSpacing(4);
        Label passwordConfirm = new Label("Подтвердите пароль");
        passwordConfirmField = new PasswordTextBox();
        passwordConfirmField.getElement().setId("pwdConfirm");

        passwordConfirmPanel.add(passwordConfirm);
        passwordConfirmPanel.add(passwordConfirmField);

        passwordConfirmError = new HorizontalPanel();
        passwordConfirmError.setSpacing(2);

        HorizontalPanel buttons = new HorizontalPanel();
        buttons.setVerticalAlignment(HorizontalPanel.ALIGN_MIDDLE);
        buttons.setSpacing(4);
        Button confirm = new Button("Сохранить");

        confirm.addClickHandler(new RegistrationHandler());

        Button cancel = new Button("Отменить");
        cancel.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                hide();
            }
        });

        buttons.add(confirm);
        buttons.add(cancel);

        registrationPanel.add(hello);
        registrationPanel.add(enterYourData);
        registrationPanel.add(loginPanel);
        registrationPanel.add(loginError);
        registrationPanel.add(firstNamePanel);
        registrationPanel.add(firstNameError);
        registrationPanel.add(lastNamePanel);
        registrationPanel.add(lastNameError);
        registrationPanel.add(affilationPanel);
        registrationPanel.add(emailPanel);
        registrationPanel.add(emailError);
        registrationPanel.add(passwordPanel);
        registrationPanel.add(passwordError);
        registrationPanel.add(passwordConfirmPanel);
        registrationPanel.add(passwordConfirmError);
        registrationPanel.add(buttons);

        add(registrationPanel);


        //======================== Field focus listeners =====================
        loginField.addFocusHandler(new FieldFocusHandler());
        loginField.addBlurHandler(new FieldBlurHandler());
        firstNameField.addFocusHandler(new FieldFocusHandler());
        firstNameField.addBlurHandler(new FieldBlurHandler());
        lastNameField.addFocusHandler(new FieldFocusHandler());
        lastNameField.addBlurHandler(new FieldBlurHandler());
        affilationField.addFocusHandler(new FieldFocusHandler());
        emailField.addFocusHandler(new FieldFocusHandler());
        emailField.addBlurHandler(new FieldBlurHandler());
        passwordField.addFocusHandler(new FieldFocusHandler());
        passwordField.addBlurHandler(new FieldBlurHandler());
        passwordConfirmField.addFocusHandler(new FieldFocusHandler());
        passwordConfirmField.addBlurHandler(new FieldBlurHandler());

    }


    class FieldBlurHandler implements BlurHandler{
        @Override
        public void onBlur(BlurEvent event) {
            Element e = ((TextBox)event.getSource()).getElement();

            //Login validation
            if("login".equals(e.getId())){

                AsyncCallback<Boolean> validation = new AsyncCallback<Boolean>() {
                    @Override
                    public void onFailure(Throwable caught) {
                         HTML error = new HTML(caught.getMessage());
                            error.setStyleName("loginErrorPanel");
                            loginError.add(error);
                            Element e = loginField.getElement();
                            DOM.setStyleAttribute(e, "background", "orange");
                    }

                    @Override
                    public void onSuccess(Boolean result) {
                        if(!result){
                            HTML error = new HTML("Допустимы латинские буквы и цифры.<br>Длина логина не менее 5 символов.");
                            error.setStyleName("loginErrorPanel");
                            loginError.add(error);
                            Element e = loginField.getElement();
                            DOM.setStyleAttribute(e, "background", "orange");
                        }
                    }
                };

                validationService.validateLogin(loginField.getText(), validation);
            }

            if("firstName".equals(e.getId())){
                if(firstNameField.getText().length()<2){
                    HTML error = new HTML("Имя должно состоять из двух и более букв");
                    error.setStyleName("loginErrorPanel");
                    firstNameError.add(error);

                    DOM.setStyleAttribute(e, "background", "orange");
                }
            }

            if("lastName".equals(e.getId())){
                if(lastNameField.getText().length()<2){
                    HTML error = new HTML("Фамилия должна состоять из двух и более букв");
                    error.setStyleName("loginErrorPanel");
                    lastNameError.add(error);

                    DOM.setStyleAttribute(e, "background", "orange");
                }
            }

            if("email".equals(e.getId())){

                AsyncCallback<Boolean> validation = new AsyncCallback<Boolean>() {
                    @Override
                    public void onFailure(Throwable caught) {
                         HTML error = new HTML(caught.getMessage());
                            error.setStyleName("loginErrorPanel");
                            emailError.add(error);
                            Element e = emailField.getElement();
                            DOM.setStyleAttribute(e, "background", "orange");
                    }

                    @Override
                    public void onSuccess(Boolean result) {
                        if(!result){
                            HTML error = new HTML("Некорректный e-mail");
                            error.setStyleName("loginErrorPanel");
                            emailError.add(error);
                            Element e = emailField.getElement();
                            DOM.setStyleAttribute(e, "background", "orange");
                        }
                    }
                };

                validationService.validateEmail(emailField.getText(), validation);
            }

            if("pwd".equals(e.getId())){
                AsyncCallback<Boolean> validation = new AsyncCallback<Boolean>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        //TODO: serverError
                    }

                    @Override
                    public void onSuccess(Boolean result) {
                        if(!result){
                            HTML error = new HTML("Допустимы латинские буквы и цифры.<br>Длина пароля не менее 5 символов.");
                            error.setStyleName("loginErrorPanel");
                            passwordError.add(error);
                            Element e = passwordField.getElement();
                            DOM.setStyleAttribute(e, "background", "orange");
                        }
                    }
                };

                validationService.validateLogin(passwordField.getText(), validation);
            }

            if("pwdConfirm".equals(e.getId())){
                if(!passwordField.getText().equals(passwordConfirmField.getText())){
                    HTML error = new HTML("Пароли не совпадают.");
                    error.setStyleName("loginErrorPanel");
                    passwordConfirmError.add(error);

                    DOM.setStyleAttribute(e, "background", "orange");
                }
            }
        }
    }

    class FieldFocusHandler implements FocusHandler {
        @Override
        public void onFocus(FocusEvent focusEvent) {

            Element e = ((TextBox)focusEvent.getSource()).getElement();
                if("login".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((loginError.getWidgetCount()>0)&&(loginError.getWidget(0)!=null)){
                        loginError.remove(0);
                    }
                }

                if("firstName".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((firstNameError.getWidgetCount()>0)&&(firstNameError.getWidget(0)!=null)){
                        firstNameError.remove(0);
                    }
                }

                if("lastName".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((lastNameError.getWidgetCount()>0)&&(lastNameError.getWidget(0)!=null)){
                        lastNameError.remove(0);
                    }
                }

                if("email".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((emailError.getWidgetCount()>0)&&(emailError.getWidget(0)!=null)){
                        emailError.remove(0);
                    }
                }

            if("pwd".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((passwordError.getWidgetCount()>0)&&(passwordError.getWidget(0)!=null)){
                        passwordError.remove(0);
                    }
                }

            if("pwdConfirm".equals(e.getId())){
                    DOM.setStyleAttribute(e, "background", "white");

                    if((passwordConfirmError.getWidgetCount()>0)&&(passwordConfirmError.getWidget(0)!=null)){
                        passwordConfirmError.remove(0);
                    }
                }
        }
    }

    class RegistrationHandler implements ClickHandler {
        @Override
        public void onClick(ClickEvent clickEvent) {
            String login = loginField.getText();
            String firstName = firstNameField.getText();
            String lastName = lastNameField.getText();
            String affilation = affilationField.getText();
            String email = emailField.getText();
            String password = passwordField.getText();
            String confirmPassword = passwordConfirmField.getText();

            boolean error = false;

            if(login.length()==0){
                Element e = loginField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            //First name validation
            if(firstName.length()==0){
                Element e = firstNameField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            //Last name validation
            if(lastName.length()==0){

                Element e = lastNameField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            //Last name validation
            if(email.length()==0){

                Element e = emailField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            //Last name validation
            if(password.length()==0){

                Element e = passwordField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            if(confirmPassword.length()==0){

                Element e = passwordConfirmField.getElement();
                DOM.setStyleAttribute(e, "background", "orange");
                error = true;
            }

            if( (loginError.getWidgetCount()>0)&&(loginError.getWidget(0)!=null) ||
                (firstNameError.getWidgetCount()>0)&&(firstNameError.getWidget(0)!=null) ||
                (lastNameError.getWidgetCount()>0)&&(lastNameError.getWidget(0)!=null) ||
                (emailError.getWidgetCount()>0)&&(emailError.getWidget(0)!=null) ||
                (emailError.getWidgetCount()>0)&&(emailError.getWidget(0)!=null) ||
                (passwordError.getWidgetCount()>0)&&(passwordError.getWidget(0)!=null) ||
                (passwordConfirmError.getWidgetCount()>0)&&(passwordConfirmError.getWidget(0)!=null)){

                error = true;
            }


            if(!error){
                User user = new User(null, login, firstName, lastName, affilation, email, password);


                AsyncCallback<User> registration = new AsyncCallback<User>() {
                    @Override
                    public void onFailure(Throwable caught) {
                        //TODO: serverError
                        int i=0;
                        if((loginError.getWidgetCount()>0)&&(loginError.getWidget(0)!=null)){
                            loginError.remove(0);
                        }

                        HTML error = new HTML(caught.getMessage());
                        error.setStyleName("loginErrorPanel");
                        loginError.add(error);

                    }

                    @Override
                    public void onSuccess(User user) {
                        if(user!=null){
                            AspectKnowledgeBaseApplication.get().setUser(user);

                        }
                    }
                };
                try {
                    registrationService.registerUser(user, registration);
                } catch (Exception e) {
                    Window.alert("Внутренняя ошибка сервера. Обратитесь к администратору");
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }

        }
    }
}
